home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / enter.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  10KB  |  492 lines

  1. /*
  2.  * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
  3.  * 
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  * 
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  * 
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */ 
  18.  
  19. #include "mutt.h"
  20. #include "mutt_menu.h"
  21. #include "mutt_curses.h"
  22. #include "keymap.h"
  23.  
  24. #include <termios.h>
  25. #include <sys/types.h>
  26. #include <fcntl.h>
  27. #include <stdlib.h>
  28. #include <unistd.h>
  29. #include <string.h>
  30. #include <errno.h>
  31. #include <ctype.h>
  32.  
  33. /* global vars used for the string-history routines */
  34. static char **Hist = NULL;
  35. static short HistCur = 0;
  36. static short HistLast = 0;
  37.  
  38. void mutt_init_history (void)
  39. {
  40.   int i;
  41.   static int OldSize = 0;
  42.   
  43.   if (Hist)
  44.   {
  45.     for (i = 0 ; i < OldSize ; i ++)
  46.       safe_free ((void **) &Hist[i]);
  47.     safe_free ((void **) &Hist);
  48.   }
  49.   
  50.   if (HistSize)
  51.     Hist = safe_calloc (HistSize, sizeof (char *));
  52.   HistCur = 0;
  53.   HistLast = 0;
  54.   OldSize = HistSize;
  55. }
  56.  
  57. static void sh_add (char *s)
  58. {
  59.   int prev;
  60.  
  61.   if (!HistSize)
  62.     return; /* disabled */
  63.  
  64.   if (*s)
  65.   {
  66.     prev = HistLast - 1;
  67.     if (prev < 0) prev = HistSize - 1;
  68.     if (!Hist[prev] || strcmp (Hist[prev], s) != 0)
  69.     {
  70.       safe_free ((void **) &Hist[HistLast]);
  71.       Hist[HistLast++] = safe_strdup (s);
  72.       if (HistLast > HistSize - 1)
  73.     HistLast = 0;
  74.     }
  75.   }
  76.   HistCur = HistLast; /* reset to the last entry */
  77. }
  78.  
  79. static char *sh_next (void)
  80. {
  81.   int next;
  82.  
  83.   if (!HistSize)
  84.     return (""); /* disabled */
  85.  
  86.   next = HistCur + 1;
  87.   if (next > HistLast - 1)
  88.     next = 0;
  89.   if (Hist[next])
  90.     HistCur = next;
  91.   return (Hist[HistCur] ? Hist[HistCur] : "");
  92. }
  93.  
  94. static char *sh_prev (void)
  95. {
  96.   int prev;
  97.  
  98.   if (!HistSize)
  99.     return (""); /* disabled */
  100.  
  101.   prev = HistCur - 1;
  102.   if (prev < 0)
  103.   {
  104.     prev = HistLast - 1;
  105.     if (prev < 0)
  106.     {
  107.       prev = HistSize - 1;
  108.       while (prev > 0 && Hist[prev] == NULL)
  109.     prev--;
  110.     }
  111.   }
  112.   if (Hist[prev])
  113.     HistCur = prev;
  114.   return (Hist[HistCur] ? Hist[HistCur] : "");
  115. }
  116.  
  117. /* redraw flags for mutt_enter_string() */
  118. enum
  119. {
  120.   M_REDRAW_INIT = 1,    /* recalculate lengths */
  121.   M_REDRAW_LINE,    /* redraw entire line */
  122.   M_REDRAW_EOL,        /* redraw from current position to eol */
  123.   M_REDRAW_PREV_EOL    /* redraw from curpos-1 to eol */
  124. };
  125.  
  126. /* Returns:
  127.  *    1 need to redraw the screen and call me again
  128.  *    0 if input was given
  129.  *     -1 if abort.
  130.  *
  131.  */
  132. int mutt_enter_string (unsigned char *buf, size_t buflen, int y, int x,
  133.                int flags)
  134. {
  135.   int curpos = 0;        /* the location of the cursor */
  136.   int lastchar = 0;         /* offset of the last char in the string */
  137.   int begin = 0;        /* first character displayed on the line */
  138.   int ch;            /* last typed character */
  139.   int width = COLS - x - 1;    /* width of field */
  140.   int redraw = M_REDRAW_INIT;    /* when/what to redraw */
  141.   int pass = (flags == M_PASS);
  142.   int first = 1;
  143.   int j;
  144.   char tempbuf[_POSIX_PATH_MAX] = "";
  145.  
  146.   FOREVER
  147.   {
  148.     if (redraw)
  149.     {
  150.       if (redraw == M_REDRAW_INIT)
  151.       {
  152.     /* full redraw */
  153.     lastchar = curpos = strlen ((char *) buf);
  154.     begin = lastchar - width;
  155.       }
  156.       if (begin < 0)
  157.     begin = 0;
  158.       switch (redraw)
  159.       {
  160.     case M_REDRAW_PREV_EOL:
  161.       j = curpos - 1;
  162.       break;
  163.     case M_REDRAW_EOL:
  164.       j = curpos;
  165.       break;
  166.     default:
  167.       j = begin;
  168.       }
  169.       move (y, x + j - begin);
  170.       for (; j < lastchar && j < begin + width; j++)
  171.     addch (buf[j]);
  172.       clrtoeol ();
  173.       if (redraw != M_REDRAW_INIT)
  174.     move (y, x + curpos - begin);
  175.       redraw = 0;
  176.     }
  177.     mutt_refresh ();
  178.  
  179.     /* first look to see if a keypress is an editor operation.  km_dokey()
  180.      * returns 0 if there is no entry in the keymap, so restore the last
  181.      * keypress and continue normally.
  182.      */
  183.     if ((ch = km_dokey (MENU_EDITOR)) == -1)
  184.     {
  185.       buf[curpos] = 0;
  186.       return (-1);
  187.     }
  188.  
  189.     if (ch != 0)
  190.     {
  191.       first = 0; /* make sure not to clear the buffer */
  192.       switch (ch)
  193.       {
  194.     case OP_EDITOR_HISTORY_UP:
  195.       if (!pass)
  196.       {
  197.         strfcpy ((char *) buf, sh_prev (), buflen);
  198.         redraw = M_REDRAW_INIT;
  199.       }
  200.       break;
  201.     case OP_EDITOR_HISTORY_DOWN:
  202.       if (!pass)
  203.       {
  204.         strfcpy ((char *) buf, sh_next (), buflen);
  205.         redraw = M_REDRAW_INIT;
  206.       }
  207.       break;
  208.     case OP_EDITOR_BACKSPACE:
  209.       if (curpos == 0)
  210.       {
  211.         BEEP ();
  212.         break;
  213.       }
  214.       for (j = curpos ; j < lastchar ; j++)
  215.         buf[j - 1] = buf[j];
  216.       curpos--;
  217.       lastchar--;
  218.       if (!pass)
  219.       {
  220.         if (curpos > begin)
  221.         {
  222.           if (lastchar == curpos)
  223.           {
  224.         move (y, x + curpos - begin);
  225.         delch ();
  226.           }
  227.           else
  228.         redraw = M_REDRAW_EOL;
  229.         }
  230.         else
  231.         {
  232.           begin -= width / 2;
  233.           redraw = M_REDRAW_LINE;
  234.         }
  235.       }
  236.       break;
  237.     case OP_EDITOR_BOL:
  238.       /* reposition the cursor at the begininning of the line */
  239.       curpos = 0;
  240.       if (!pass)
  241.       {
  242.         if (begin)
  243.         {
  244.           /* the first char is not displayed, so readjust */
  245.           begin = 0;
  246.           redraw = M_REDRAW_LINE;
  247.         }
  248.         else
  249.           move (y, x);
  250.       }
  251.       break;
  252.     case OP_EDITOR_EOL:
  253.       curpos = lastchar;
  254.       if (!pass)
  255.       {
  256.         if (lastchar < begin + width)
  257.           move (y, x + lastchar - begin);
  258.         else
  259.         {
  260.           begin = lastchar - width / 2;
  261.           redraw = M_REDRAW_LINE;
  262.         }
  263.       }
  264.       break;
  265.     case OP_EDITOR_KILL_LINE:
  266.       lastchar = curpos = 0;
  267.       if (!pass)
  268.       {
  269.         begin = 0;
  270.         redraw = M_REDRAW_LINE;
  271.       }
  272.       break;
  273.     case OP_EDITOR_KILL_EOL:
  274.       lastchar = curpos;
  275.       if (!pass)
  276.         clrtoeol ();
  277.       break;
  278.     case OP_EDITOR_BACKWARD_CHAR:
  279.       if (curpos == 0)
  280.       {
  281.         BEEP ();
  282.       }
  283.       else
  284.       {
  285.         curpos--;
  286.         if (!pass)
  287.         {
  288.           if (curpos < begin)
  289.           {
  290.         begin -= width / 2;
  291.         redraw = M_REDRAW_LINE;
  292.           }
  293.           else
  294.         move (y, x + curpos - begin);
  295.         }
  296.       }
  297.       break;
  298.     case OP_EDITOR_FORWARD_CHAR:
  299.       if (curpos == lastchar)
  300.       {
  301.         BEEP ();
  302.       }
  303.       else
  304.       {
  305.         curpos++;
  306.         if (!pass)
  307.         {
  308.           if (curpos >= begin + width)
  309.           {
  310.         begin = curpos - width / 2;
  311.         redraw = M_REDRAW_LINE;
  312.           }
  313.           else
  314.         move (y, x + curpos - begin);
  315.         }
  316.       }
  317.       break;
  318.     case OP_EDITOR_DELETE_CHAR:
  319.       if (curpos != lastchar)
  320.       {
  321.         for (j = curpos; j < lastchar; j++)
  322.           buf[j] = buf[j + 1];
  323.         lastchar--;
  324.         if (!pass)
  325.           redraw = M_REDRAW_EOL;
  326.       }
  327.       else
  328.         BEEP ();
  329.       break;
  330.     case OP_EDITOR_KILL_WORD:
  331.       /* delete to begining of word */
  332.       if (curpos != 0)
  333.       {
  334.         j = curpos;
  335.         while (j > 0 && ISSPACE (buf[j - 1]))
  336.           j--;
  337.         if (j > 0)
  338.         {
  339.           if (isalnum (buf[j - 1]))
  340.           {
  341.         for (j--; j > 0 && isalnum (buf[j - 1]); j--)
  342.           ;
  343.           }
  344.           else
  345.         j--;
  346.         }
  347.         ch = j; /* save current position */
  348.         while (curpos < lastchar)
  349.           buf[j++] = buf[curpos++];
  350.         lastchar = j;
  351.         curpos = ch; /* restore current position */
  352.         /* update screen */
  353.         if (!pass)
  354.         {
  355.           if (curpos < begin)
  356.           {
  357.         begin = curpos - width / 2;
  358.         redraw = M_REDRAW_LINE;
  359.           }
  360.           else
  361.         redraw = M_REDRAW_EOL;
  362.         }
  363.       }
  364.       break;
  365.     default:
  366.       BEEP ();
  367.       }
  368.     }
  369.     else
  370.     {
  371.       /* use the raw keypress */
  372.       ch = LastKey;
  373.  
  374.       if ((flags & M_EFILE) && ch == ' ')
  375.       {
  376.     buf[curpos] = 0;
  377.     mutt_buffy ((char *) buf);
  378.     redraw = M_REDRAW_INIT;
  379.     continue;
  380.       }
  381.  
  382.       if (first && (flags & M_CLEAR))
  383.       {
  384.     first = 0;
  385.     if (IsPrint (ch))
  386.     {
  387.       mutt_ungetch (ch);
  388.       buf[0] = 0;
  389.       redraw = M_REDRAW_INIT;
  390.       continue;
  391.     }
  392.       }
  393.  
  394.       if ((flags & (M_FILE | M_EFILE)) && (ch == '\t' || ch == ' '))
  395.       {
  396.     buf[curpos] = 0;
  397.  
  398.     /* see if the path has changed from the last time */
  399.     if (strcmp (tempbuf, (char *) buf) == 0)
  400.     {
  401.       mutt_select_file ((char *) buf, buflen, 0);
  402.       set_option (OPTNEEDREDRAW);
  403.       if (buf[0])
  404.       {
  405.         mutt_prett